package com.atguigu.gmall.order.receiver;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.model.payment.PaymentInfo;
import com.atguigu.gmall.order.service.OrderService;
import com.atguigu.gmall.payment.client.PaymentFeignClient;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Map;

@Component
public class OrderReceiver {

    @Autowired
    private OrderService orderService;

    @Autowired
    private PaymentFeignClient paymentFeignClient;


    //  监听消息；
    @SneakyThrows
    @RabbitListener(queues = MqConst.QUEUE_ORDER_CANCEL)
    public void orderCancel(Long orderId, Message message, Channel channel){
        //  判断
        try {
            if (orderId!=null){
                //  实现查询订单是否支付.
                OrderInfo orderInfo = orderService.getById(orderId);

                //  订单状态是未支付.
                if (orderInfo!=null && "UNPAID".equals(orderInfo.getOrderStatus())
                    && "UNPAID".equals(orderInfo.getProcessStatus())
                   ){
                    //  有了orderInfo 一定会有paymentInfo 么？ 不一定！ paymentInfo 只有在 点击支付宝的扫码支付时候。
                    PaymentInfo paymentInfo =  paymentFeignClient.getPaymentInfo(orderInfo.getOutTradeNo());
                    //  判断
                    if (paymentInfo!=null && "UNPAID".equals(paymentInfo.getPaymentStatus())){
                        //  说明里面有交易记录,才有可能会关闭支付宝交易.
                        //  判断用户是否扫码了： 扫码了，才调用关闭 ，如果都没有扫码，不用调用关闭支付宝接口.
                        Boolean result = this.paymentFeignClient.checkPayment(orderId);
                        if (result){
                            //  result = true 扫码了。
                            //  只有存在交易记录，才能判断是否要关闭支付宝的交易记录.
                            //  调用关闭支付宝交易记录方法.
                            Boolean exist = this.paymentFeignClient.closePay(orderId);
                            //  如果用户支付成功了。那么就会关闭失败.
                            if (exist){
                                //  exist = true; 说明关闭成功了。 说明没有付款。 还需要关闭 orderInfo、 paymentInfo;
                                this.orderService.execExpiredOrder(orderId,"2");
                            }else {
                                //  说明没有关闭成功. 有可能在一瞬间用户付款了。
                            }
                        }else {
                            //  需要关闭orderInfo ，paymentInfo;
                            orderService.execExpiredOrder(orderId,"2");
                        }
                    }else {
                        //  说没有交易记录.
                        //  取消订单业务. 只需要关闭orderInfo；
                        orderService.execExpiredOrder(orderId,"1");
                    }
                }else {
                    //  orderInfo 存在，但是不是未付款.
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //  手动确认消息
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

    //  监听支付成功之后发送的消息;
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_PAYMENT_PAY,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_PAYMENT_PAY),
            key = {MqConst.ROUTING_PAYMENT_PAY}
    ))
    public void updateOrder(Long orderId,Message message, Channel channel){
        try {
            //  判断
            if (orderId!=null){
                //  根据订单Id 更新状态.
                OrderInfo orderInfo = this.orderService.getById(orderId);
                if (orderInfo!=null && "UNPAID".equals(orderInfo.getOrderStatus())){
                    orderService.updateOrderStatus(orderId, ProcessStatus.PAID);
                    //  发送消息给库存，通知减库存.
                    orderService.sendOrderStatus(orderId);
                }
            }
        } catch (Exception e) {
            //  记录日志表.
            e.printStackTrace();
        }
        //  手动确认消息.
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

    //  订单监听减库存结果.
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_WARE_ORDER,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_WARE_ORDER),
            key = {MqConst.ROUTING_WARE_ORDER}
    ))
    public void updOrder(String jsonStr,Message message,Channel channel){
        try {
            // 判断
            if (!StringUtils.isEmpty(jsonStr)){
                //  jsonStr ---> Map;
                Map map = JSON.parseObject(jsonStr, Map.class);
                String orderId = (String) map.get("orderId");
                String status = (String) map.get("status");
                //  再次判断：
                if ("DEDUCTED".equals(status)){
                    //  说明扣减库存成功. 更新订单的状态.
                    this.orderService.updateOrderStatus(Long.parseLong(orderId),ProcessStatus.WAITING_DELEVER);
                }else {
                    //  扣减库存失败.
                    this.orderService.updateOrderStatus(Long.parseLong(orderId),ProcessStatus.STOCK_EXCEPTION);
                    //  日志，信息提醒！
                    //  处理方式两种： 一种： 补货  二种： 人工客服.
                }
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        //  手动确认消息.
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }
}
